/* test_threads_func_uthread_cancel():
	A test for uthread_cancel(). Test the regular case + the UTHREAD_INVALID error cases.

	* Does a uthread_cancel() to an invalid thread id (here and there and everywhere).
	* Creates threads 1,2.
	* thread 2 does join to thread 1.
	* Thread 0 does cancel to thread 1.
	* Thread 0 does cancel to thread 2 (when its just looping infinitly).
*/

#include <stdio.h>
#include <stdbool.h>
#include "test_general.h"
#include "user_threads.h"

bool test_threads_func_uthread_cancel();

#define THREADS_NUM 3

static int thread1_start_routine(void * param) {
	TEST_ASSERT( 53 == (*((int*)param)) );

	TEST_ASSERT (uthread_self() == 1);

	thread_ok[1] = true;

	while (true){}
}

static int thread2_start_routine(void * param) {
	TEST_ASSERT( 53 == (*((int*)param)) );

	TEST_ASSERT (uthread_self() == 2);

	int tmp, tmp2;
	tmp = uthread_join(1,&tmp2);
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);
	TEST_ASSERT(UTHREAD_CANCELLED == tmp2);

	thread_ok[2] = true;
	while (true) {}
}


bool test_threads_func_uthread_cancel()
{
	init_individual_test();

	int tmp, tmp2;

/*	if (initilize_uthread_in_each_test) {
		tmp = uthread_init();
		TEST_ASSERT(tmp == UTHREAD_SUCCESS);
	}*/


	/* Checking: UTHREAD_INVALID */
	tmp = uthread_cancel(-1);
	TEST_ASSERT(UTHREAD_INVALID == tmp);
	tmp = uthread_cancel(1);
	TEST_ASSERT(UTHREAD_INVALID == tmp);



	uthread_id threads[THREADS_NUM];

	threads[0] = uthread_self();



	int FiftyThree = 53;

	threads[1] = uthread_create(thread1_start_routine, &FiftyThree);
	TEST_ASSERT(threads[1] == 1);

	threads[2] = uthread_create(thread2_start_routine, &FiftyThree);
	TEST_ASSERT(threads[2] == 2);

	tmp = uthread_cancel(3);
	TEST_ASSERT(UTHREAD_INVALID == tmp);


	some_long_operation(0.1);

	tmp = uthread_cancel(threads[1]);
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);

	some_long_operation(0.1);

	tmp = uthread_cancel(threads[2]);
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);

	tmp = uthread_join(threads[2],&tmp2);
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);
	TEST_ASSERT(UTHREAD_CANCELLED == tmp2);



	thread_ok[0] = true;
	TEST_ASSERT(are_all_threads_ok(THREADS_NUM));

	return true;
}
